#ifndef ISA_H
#define ISA_H

// registers
enum{ REG_RA, REG_RB, REG_RC, REG_RD,
	REG_SP, REG_BP, REG_SI, REG_DI, REG_IH,
	REG_PDIR, REG_FLAGS, REG_NONE} reg_id_t;

// instructions
enum{ I_HALT, I_NOP, I_RRMOV, I_IRMOV, I_STORE, I_LOAD, I_ADD, I_SUB,
	I_AND, I_OR, I_NOT, I_XOR, I_SHL, I_SHR, I_JMP, I_JE, I_JL, I_JG, I_JNE, 
	I_JLE, I_JGE, I_CALL, I_INT, I_RET, I_IRET, I_PUSH, I_POP, I_IN, I_OUT,
	I_NONE} instr_id_t;

// mapping of registers
static struct {
  const char *name;	// name of regs
  unsigned int value;	// value of regs
} reg_table[REG_NONE] =	//NOTE: order of reg_table[] MUST BE CONSISTENT WITH enum reg_id_t.
{
  {"%ra", 0},
  {"%rb", 0},
  {"%rc", 0},
  {"%rd", 0},
  {"%sp", 0},
  {"%bp", 0},
  {"%si", 0},
  {"%di", 0},
  {"%ih", 0},
  {"%pdir", 0},
  {"%flags", 0}	//CF:0, ZF:6, SF:7, IF:9, OF:11, PL:12, PG:31
};

// mapping of instructions
static struct {
  const char *name;
  const char value;
} instr_table[I_NONE] = //NOTE: order of instr_table[] MUST BE CONSISTENT WITH enum instr_id_t.
{
  {"halt", 0x0},
  {"nop", 0x10},
  {"rrmov", 0x20},
  {"irmov", 0x30},
  {"store", 0x40},
  {"load", 0x50},
  {"add", 0x60},
  {"sub", 0x61},
  {"and", 0x62},
  {"or", 0x63},
  {"not", 0x64},
  {"xor", 0x65},
  {"shl", 0x66},
  {"shr", 0x67},
  {"jmp", 0x70},
  {"je", 0x71},
  {"jl", 0x72},
  {"jg", 0x73},
  {"jne", 0x74},
  {"jle", 0x75},
  {"jge", 0x76},
  {"call", 0x80},
  {"int", 0x81},
  {"ret", 0x90},
  {"iret", 0x91},
  {"push", 0xa0},
  {"pop", 0xb0},
  {"in", 0xc0},
  {"out", 0xd0}
};
#endif
